<?php
/**
 * token操作类
 * 
 * @author Leo
 * @since 2012.2.24
 */
class Helper_Token
{
    /**
     * 用户Id
     * @var int
     */
    protected $uId;
    
    /**
     * token过期天数
     * @var int
     */
    protected $expires;

    /**
     * 单例对象
     * @var array
     */
    protected static $singletonObjects = array();

    /**
     * 构造函数
	 * @param int $uId          用户ID
     * @param int $expires      token过期时间
     */
    private function __construct( $uId , $expires = 0 )
    {
        $this->uId = $uId;
        $this->expires = $expires;
    }
    
    /**
	 * 获取单例
	 * @param int $uId          用户ID
     * @param int $expires      token过期时间
	 * @return Helper_Token
	 * @throws AppException
	 */
	public static function getInstance( $uId , $expires = 0 )
	{
		$className = __CLASS__;
		if( !isset( self::$singletonObjects[$uId][$className] ) )
		{
			self::$singletonObjects[$uId][$className] = new self( $uId , $expires );
		}

		return self::$singletonObjects[$uId][$className];
	}

    /**
     * 获取token
     * 
     * @return string
     */
    public function createToken()
    {
        //获取用户密码信息
        $passwdHash = User_Info::getInstance( $this->uId )->getInfoUserPasswd();
        
        return self::_encode( $this->uId . '|' . $passwdHash . '|' . $_SERVER['REQUEST_TIME'] );
    }
    
    /**
     * 解析token
     * 
     * @param string $token
     * @return string 
     */
    public function analyToken( $token )
    {
        //解析token
        $result = self::_decode( $token );
        
        $data = explode( '|' , $result );
        
        if( $data[0] != $this->uId )
        {
            throw new AppException( 4 );
        }
        
        //验证密码
        $passwd = User_Info::getInstance( $this->uId )->getInfoUserPasswd();
        if( empty( $passwd ) || $data[1] != $passwd )
        {
            throw new AppException( 4 );
        }
        
        //验证TOKEN是否过期（30天）
        if( $this->expires > 0 )
        {
            if( $data[2] + (int)$this->expires * 86400 < $_SERVER['REQUEST_TIME'] )
            {
                throw new AppException( 4 );
            }
        }
        
        return $token;
    }
    
    /** 
    * Mcrypt 加密
    * 
    * @param String $data 要加密和解密的数据 
    * @return String 
    * @author Leo
    */
    private static function _encode( $data )
    {
        $txt = trim( $data );
        
        $key = MD5( Common::getConfig( 'apiSecret' ) );
        
        for( $i = 0 , $j = 0; $i < strlen( $txt ); $i++ )
        {
             if( $j === strlen( $key ) )
             {
                 $j = 0;
             }
             $str .= substr( $txt , $i , 1 ) ^ substr( $key , $j , 1 );
             $j++;
        }
        
        return base64_encode( $str );
    }
    
    /**
     * 解密
     * @param string $token
     * @return string
     */
    private static function _decode( $token )
    {
        $txt = base64_decode( $token );
        
        $key = MD5( Common::getConfig( 'apiSecret' ) );
        
        $str = '';
        for( $i = 0 , $j = 0; $i < strlen( $txt ); $i++ )
        {
            if( $j === strlen( $key ) )
            {
                $j = 0;
            }
            $str .= substr( $txt , $i , 1 ) ^ substr( $key , $j , 1 );
            $j++ ;
        }
        
        return $str;
    }
} 
